package com.guanghua.brick.html.tag;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.guanghua.brick.html.ConfigContent;
import com.guanghua.brick.html.IContent;
import com.guanghua.brick.html.IControl;
import com.guanghua.brick.html.SQLContent;
import com.guanghua.brick.util.IConfig;
import com.guanghua.brick.util.XmlReader;

public class ContentConfigTag extends BodyTagSupport {
	
	private static Log logger = LogFactory.getLog(ContentConfigTag.class);
	
	private ConfigContent content = new ConfigContent();
	public void addRow(Map<String,String> map) {content.addRow(map);}
	public void clearRow() {content.clearRow();}
	public String getId() {return content.getId();}
	public void setId(String id) {
		content.setId(ContentConfigTag.getPagePrefix((HttpServletRequest)pageContext.getRequest(), id));
	}
	public List<Map<String, String>> getList() {
		return content.getList();
	}
	public void setList(List<Map<String, String>> list) {
		content.setList(list);
	}
	
	
	private String textProperty = "text";
	public String getTextProperty() {
		return textProperty;
	}
	public void setTextProperty(String textProperty) {
		this.textProperty = textProperty;
	}
	
	private String valueProperty = "value";
	public String getValueProperty() {
		return valueProperty;
	}
	public void setValueProperty(String valueProperty) {
		this.valueProperty = valueProperty;
	}
	
	public int doEndTag() throws JspException {
		//获取content pool，并将content放入
		Map<String, IContent> pool = getContentPool(pageContext.getServletContext());
		pool.put(content.getId(), content);
		logger.trace("content id: " + content.getId());
		logger.trace("content cls: " + content.toString());
		
		//设置父控件中的content属性
		Tag parent = this.getParent();
		if (parent instanceof IControl) {
			((IControl)parent).setContent(content);
		}
		return BodyTagSupport.EVAL_PAGE;
	}
	
	
	/**
	 * 获取并且初始化content pool的方法
	 * @param pageContext
	 * @return
	 */
	
	@SuppressWarnings("unchecked")
	public static Map<String, IContent> getContentPool(ServletContext servletContext) {
		Map<String, IContent> map = (Map<String, IContent>)servletContext.getAttribute(IContent.CONTENT_POOL);
		if (map == null) {
			//创建map
			map = new HashMap<String, IContent>();
			
			//初始化brick.web.xml中的content
			IConfig[] configs = null;
			try {
				//读取配置
				XmlReader reader = new XmlReader(servletContext.getRealPath("/WEB-INF/brick.web.xml"), true);
				configs = reader.readChildByTagName("web-control-content");
			} catch (Exception e) {
				logger.error("parse xml /web-inf/brick.web.xml to find web control content error", e);
			}
				
			if (configs != null) {
				//根据配置初始化不同的content
				logger.debug("start to init content in brick.web.xml");
				for (IConfig c : configs) {
					String id = c.getAttribute("id");
					if (id == null || id.length() == 0) {
						logger.warn("the content config in brick.web.xml must have id attr");
						continue;
					}
					
					logger.debug("start to init content which id is [" + id + "]");
					if ("config".equals(c.getAttribute("type"))) {
						IConfig[] items = c.getChildren("item");
						if (items == null || items.length == 0) {
							logger.warn("the config config in brick.web.xml must have item child");
							continue;
						}
						String textProperty = c.getAttribute("textProperty");
						if (textProperty == null || textProperty.length() == 0) textProperty = "text";
						String valueProperty = c.getAttribute("valueProperty");
						if (valueProperty == null || valueProperty.length() == 0) valueProperty = "value";
						
						ConfigContent content = new ConfigContent();
						content.setId(id);
						//解析子节点配置，放入content
						for (IConfig i: items) {
							String t = i.getAttribute("text");
							String v = i.getAttribute("value");
							if (t != null && t.length() != 0 && v != null && v.length() != 0) {
								Map<String, String> m = new HashMap<String, String>();
								m.put(textProperty, t);
								m.put(valueProperty, v);
								content.addRow(m);
							}
						}
						logger.debug("init config type content which id is [" + id + "], and content is [" + content + "]");
						map.put(content.getId(), content);
					//sql 类型 content
					} else if ("sql".equals(c.getAttribute("type"))) {
						
						//检查sql配置
						String sql = c.getText();
						if (sql == null || sql.length() == 0) {
							logger.warn("the sql content config in brick.web.xml must have sql text node");
							continue;
						}
						
						boolean cache = !"false".equals(c.getAttribute("cache"));
						
						//创建content
						SQLContent content = new SQLContent();
						content.setId(id);						
						content.setSql(sql);
						content.setCache(cache);
						logger.debug("init sql type content which id is [" + id + "], and content is [" + content + "]");
						map.put(content.getId(), content);
					//bean 类型 content
					} else if ("bean".equals(c.getAttribute("type"))) {
						String clazz = c.getAttribute("bean");
						try {
							//创建content
							IContent content = (IContent) Class.forName(clazz).newInstance();
							content.setId(id);
							logger.debug("init bean type content which id is [" + id + "], and content is [" + content + "]");
							map.put(content.getId(), content);
						} catch (Exception ex) {
							logger.error("the bean content config in brick.web.xml load bean attr error:" + clazz, ex);
						}
						
					} else {
						logger.warn("the content config in brick.web.xml must have type attr or type must be config, sql, bean");
					}
				}
			}
			servletContext.setAttribute(IContent.CONTENT_POOL, map);
		}
		logger.trace("pool's class instance id:[" + map + "]");
		return map;
	}
	
	//处理ct的id
	public static String getPagePrefix(HttpServletRequest req, String id) {
		String path = req.getServletPath() + "." + id;
		return path.replace('/', '.');
	}
}
